package net.wyy.ssoserver;

import net.wyy.ssocore.ServletUtils;
import net.wyy.ssoserver.dto.ResultDto;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

/**
 * Created by Enzo Cotter on 2019/11/21.
 */
@SpringBootApplication
@Controller
public class ServerApp {
    public static void main(String[] args) {
        SpringApplication.run(ServerApp.class,args);
    }
    private Set<String> userList = new HashSet<>();
    {
        userList.add("tcsls/zdsoft123");
        userList.add("jack/tom");
    }
    @Value("${server.port}")
    private String port;

    @ResponseBody
    @RequestMapping("/")
    public String any(HttpServletRequest req){
        ServletUtils.printJsessionId(req, true);
        return "sso server";
    }
    @RequestMapping("/login")
    public String login(String serviceUrl, HttpServletRequest request, ModelMap model){
        ServletUtils.printJsessionId(request, true);

        if(StringUtils.isBlank(serviceUrl)){
            return errorFtl(model,"请通过合法途径访问本网站");
        }

        String name = validateByCookie(request);
        if(StringUtils.isNotBlank(name)){
            String token = createToken(request, name);
            serviceUrl = getServiceUrl(request,serviceUrl, token);
            return "redirect:"+serviceUrl;
        }

        model.put("serviceUrl",serviceUrl);
        return "/login";
    }

    private String errorFtl(ModelMap model, String errMsg) {
        model.put("msg",errMsg);
        return "/error";
    }

    private String validateByCookie(HttpServletRequest request) {
        return (String) request.getSession().getAttribute("userId");
    }

    @ResponseBody
    @RequestMapping("/doLogin")
    public ResultDto login(String serviceUrl, String name, String passwd, HttpServletRequest req, HttpServletResponse response) throws IOException {
        boolean val = checkUser(name,passwd);
        ServletUtils.printJsessionId(req, true);
        if(val){
            String token = createToken(req, name);
            serviceUrl = getServiceUrl(req, serviceUrl, token);
            return new ResultDto().setSuccess(true).setRedirectUrl(serviceUrl);
        }
        // 验证未通过
        return new ResultDto().setSuccess(false).setMsg("用户名或密码错误");
    }

    private String getServiceUrl(HttpServletRequest request, String serviceUrl, String token) {
        if(StringUtils.isBlank(serviceUrl)){
            serviceUrl = request.getScheme()+"://"+request.getHeader("host");
        }
        if(!serviceUrl.contains("?")){
            serviceUrl += "?token="+token;
        }else{
            serviceUrl += "&token="+token;
        }
        return serviceUrl;
    }

    private String createToken(HttpServletRequest req, String name) {
        req.getSession().setAttribute("userId",name);
        ServletUtils.printJsessionId(req, true);
        String token  = "token/"+name;
        req.getServletContext().setAttribute(token,name);
        return token;
    }

    private boolean checkUser(String name, String passwd) {
        boolean contains = userList.contains(name + "/" + passwd);
        return contains;
    }

    @ResponseBody
    @RequestMapping("/validate")
    public Boolean validate(String token,HttpServletRequest req){
        if(StringUtils.isBlank(token)){
            return false;
        }

        String userId = (String)req.getServletContext().getAttribute(token);
        if(StringUtils.isBlank(userId)){
            return false;
        }
        // 删除 token, 防止 token 泄露导致恶意登陆
        req.getServletContext().removeAttribute(token);
        return true;
    }
}
